package com.ziq.base.transition

import android.app.Activity
import android.app.SharedElementCallback
import android.content.Context
import android.content.Intent
import android.graphics.Matrix
import android.graphics.RectF
import android.os.Parcelable
import android.view.View
import android.view.Window
import androidx.core.app.ActivityCompat
import androidx.core.app.ActivityOptionsCompat
import androidx.core.util.Pair
import androidx.core.view.ViewCompat

class TransitionHelper {


    companion object {

        fun startActivity(activity: Activity, intent: Intent){
            val pairs: MutableList<Pair<View, String>> = mutableListOf()
            val options = ActivityOptionsCompat.makeSceneTransitionAnimation(activity, *pairs.toTypedArray())
            ActivityCompat.startActivity(activity, intent, options.toBundle())
        }

        //需要 FEATURE_ACTIVITY_TRANSITIONS
        //在 super.oncreate 之前设置, 或在主题设置
        //activity.window.requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS)
        fun setUpTransition(
            activity: Activity,
            shareElementInfoList: (() -> List<ShareElementInfo<*>>)?,
            transitionFactory: IShareElementTransitionFactory = DefaultShareElementTransitionFactory(),
        ){

            //是否覆盖执行，其实可以理解成是否同时执行还是顺序执行 false顺序执行
            activity.window.allowEnterTransitionOverlap = true
            activity.window.allowReturnTransitionOverlap = true
            //是否在透明层做动画，false 会受到 其他转场动画影响
            activity.window.sharedElementsUseOverlay = true

            val customEnterTransition = transitionFactory.buildEnterTransition()
            val customExitTransition = transitionFactory.buildExitTransition()
            activity.window.enterTransition = customEnterTransition
            activity.window.exitTransition = customExitTransition
            activity.window.reenterTransition = customExitTransition
            activity.window.returnTransition = customEnterTransition
            //防止状态栏闪烁
            val enterTransition = activity.window.enterTransition
            val exitTransition = activity.window.exitTransition
            if (enterTransition != null) {
                enterTransition.excludeTarget(Window.STATUS_BAR_BACKGROUND_TRANSITION_NAME, true)
                enterTransition.excludeTarget(
                    Window.NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME,
                    true
                )
            }
            if (exitTransition != null) {
                exitTransition.excludeTarget(Window.STATUS_BAR_BACKGROUND_TRANSITION_NAME, true)
                exitTransition.excludeTarget(Window.NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME, true)
            }

            activity.window.sharedElementEnterTransition = transitionFactory.buildShareElementEnterTransition()
            activity.window.sharedElementExitTransition = transitionFactory.buildShareElementExitTransition()

            activity.setEnterSharedElementCallback(object : SharedElementCallback() {
                override fun onMapSharedElements(
                    names: MutableList<String>?,
                    sharedElements: MutableMap<String, View>?
                ) {
                    mapSharedElements(names, sharedElements, shareElementInfoList)
                }

                override fun onCreateSnapshotView(context: Context?, snapshot: Parcelable?): View? {
                    val view : View?
                    if(snapshot is ShareElementInfo.ShareElementInfoData<*>){
                        view = super.onCreateSnapshotView(context, snapshot.snapShot)
                        ShareElementInfo.ShareElementInfoData.saveToView(view, snapshot)
                    } else {
                        view = super.onCreateSnapshotView(context, snapshot)
                    }
                    return view
                }

                override fun onSharedElementStart(
                    sharedElementNames: MutableList<String>?,
                    sharedElements: MutableList<View>?,
                    sharedElementSnapshots: MutableList<View>?
                ) {
                    if(sharedElements?.isNotEmpty() == true && sharedElementSnapshots?.isNotEmpty() == true){
                        val length = sharedElementSnapshots.size
                        for (i in 0 until length){
                            val shareElementView = sharedElements.get(i)
                            val snapshotView = sharedElementSnapshots.get(i)
                            var info = ShareElementInfo.ShareElementInfoData.getFromView(snapshotView)
                            if(info == null){
                                info = ShareElementInfo.ShareElementInfoData.getFromView(shareElementView)
                            }
                            info?.updateByView(ShareElementInfo.ShareElementInfoData.DATA_STATUS_START, shareElementView)
                            ShareElementInfo.ShareElementInfoData.saveToView(shareElementView, info)
                        }
                    }
                }

                override fun onSharedElementEnd(
                    sharedElementNames: MutableList<String>?,
                    sharedElements: MutableList<View>?,
                    sharedElementSnapshots: MutableList<View>?
                ) {
                    if(sharedElements?.isNotEmpty() == true && sharedElementSnapshots?.isNotEmpty() == true){
                        val length = sharedElementSnapshots.size
                        for (i in 0 until length){
                            val shareElementView = sharedElements.get(i)
                            val snapshotView = sharedElementSnapshots.get(i)
                            var info = ShareElementInfo.ShareElementInfoData.getFromView(snapshotView)
                            if(info == null){
                                info = ShareElementInfo.ShareElementInfoData.getFromView(shareElementView)
                            }
                            info?.updateByView(ShareElementInfo.ShareElementInfoData.DATA_STATUS_END, shareElementView)
                            ShareElementInfo.ShareElementInfoData.saveToView(shareElementView, info)
                        }
                    }
                }


            })
            activity.setExitSharedElementCallback(object : SharedElementCallback() {
                override fun onMapSharedElements(
                    names: MutableList<String>?,
                    sharedElements: MutableMap<String, View>?
                ) {
                    mapSharedElements(names, sharedElements, shareElementInfoList)
                }

                override fun onCaptureSharedElementSnapshot(
                    sharedElement: View?,
                    viewToGlobalMatrix: Matrix?,
                    screenBounds: RectF?
                ): Parcelable {
                    val snapshot = super.onCaptureSharedElementSnapshot(sharedElement, viewToGlobalMatrix, screenBounds)
                    var clz : Class<ShareElementInfoDataUpdate>? = null
                    shareElementInfoList?.invoke()?.let { list ->
                        for (info in list) {
                            if (info.getView() == sharedElement){
                                clz = info.clz as Class<ShareElementInfoDataUpdate>?
                                break
                            }
                        }
                    }
                    val shareElementInfoData = ShareElementInfo.ShareElementInfoData(snapshot, clz)
                    shareElementInfoData.updateByView(ShareElementInfo.ShareElementInfoData.DATA_STATUS_CAPTURE_SNAPSHOT, sharedElement)
                    return shareElementInfoData
                }
            })



        }

        private fun mapSharedElements(
            names: MutableList<String>?,
            sharedElements: MutableMap<String, View>?,
            shareElementInfoList: (() -> List<ShareElementInfo<*>>)?,
        ) {
            names?.clear()
            sharedElements?.clear()
            shareElementInfoList?.invoke()?.let { list ->
                for (info in list) {
                    val view: View = info.getView()
                    ViewCompat.getTransitionName(view)?.let {
                        names?.add(it)
                        sharedElements?.put(it, view)
                    }
                }
            }
        }


    }
}